home *** CD-ROM | disk | FTP | other *** search
/ The Mac Mega CD - Killer Software / The Mac Mega CD - Killer Software (May 1996).dmg / Shareware City / Sound / MacMikMod 2.10+src / source / load_m15.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-02  |  6.6 KB  |  333 lines  |  [TEXT/CWIE]

  1. /*
  2.  
  3. Name:
  4. LOAD_M15.C
  5.  
  6. Description:
  7. 15 instrument MOD loader
  8.  
  9. Portability:
  10. All systems - all compilers (hopefully)
  11.  
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include "mikmod.h"
  18.  
  19. /*************************************************************************
  20. *************************************************************************/
  21.  
  22.  
  23. typedef struct MSAMPINFO{       /* sample header as it appears in a module */
  24.         char  samplename[22];
  25.     UWORD length;
  26.     UBYTE finetune;
  27.     UBYTE volume;
  28.     UWORD reppos;
  29.     UWORD replen;
  30. } MSAMPINFO;
  31.  
  32.  
  33. typedef struct MODULEHEADER{                 /* verbatim module header */
  34.         char       songname[20];                /* the songname.. */
  35.     MSAMPINFO  samples[15];                         /* all sampleinfo */
  36.     UBYTE      songlength;                          /* number of patterns used */
  37.     UBYTE      magic1;                                      /* should be 127 */
  38.     UBYTE      positions[128];                      /* which pattern to play at pos */
  39. } MODULEHEADER;
  40.  
  41.  
  42. typedef struct MODNOTE{
  43.     UBYTE a,b,c,d;
  44. } MODNOTE;
  45.  
  46.  
  47. /*************************************************************************
  48. *************************************************************************/
  49.  
  50. static MODULEHEADER *mh;        /* raw as-is module header */
  51. static MODNOTE *patbuf;
  52.  
  53. char *strdup(char *str)
  54. {
  55.     char *rstr;
  56.     
  57.     rstr = (char*) malloc(strlen(str));
  58.     strcpy(rstr, str);
  59.     
  60.     return rstr;
  61. }
  62.  
  63. static BOOL LoadModuleHeader(MODULEHEADER *mh)
  64. {
  65.     int t;
  66.  
  67.     _mm_read_str(mh->songname,20,modfp);
  68.  
  69.     for(t=0;t<15;t++){
  70.         MSAMPINFO *s= &mh->samples[t];
  71.         _mm_read_str(s->samplename,22,modfp);
  72.         s->length    =_mm_read_M_UWORD(modfp);
  73.         s->finetune    =_mm_read_UBYTE(modfp);
  74.         s->volume    =_mm_read_UBYTE(modfp);
  75.         s->reppos    =_mm_read_M_UWORD(modfp);
  76.         s->replen    =_mm_read_M_UWORD(modfp);
  77.     }
  78.  
  79.     mh->songlength    =_mm_read_UBYTE(modfp);
  80.     mh->magic1        =_mm_read_UBYTE(modfp);                                      /* should be 127 */
  81.     _mm_read_UBYTES(mh->positions,128,modfp);
  82.  
  83.     return(!feof(modfp));
  84. }
  85.  
  86.  
  87.  
  88. BOOL M15_Test(void)
  89. {
  90.     int t;
  91.     MODULEHEADER mh;
  92.  
  93.     if(!LoadModuleHeader(&mh)) return 0;
  94.  
  95.     for(t=0;t<15;t++){
  96.  
  97.         /* all finetunes should be zero */
  98.         if(mh.samples[t].finetune!=0) return 0;
  99.  
  100.         /* all volumes should be <=64 */
  101.         if(mh.samples[t].volume>64) return 0;
  102.     }
  103.     if(mh.magic1>127) return 0;    /* and magic1 should be <128 */
  104.  
  105.     return 1;
  106. }
  107.  
  108.  
  109. BOOL M15_Init(void)
  110. {
  111.     patbuf=NULL;
  112.     if(!(mh=(MODULEHEADER *)MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
  113.     return 1;
  114. }
  115.  
  116.  
  117. void M15_Cleanup(void)
  118. {
  119.     if(mh!=NULL) free(mh);
  120.     if(patbuf!=NULL) free(patbuf);
  121. }
  122.  
  123.  
  124. /*
  125.  
  126. Old (amiga) noteinfo:
  127.  
  128.  _____byte 1_____   byte2_    _____byte 3_____   byte4_
  129. /                \ /      \  /                \ /      \
  130. 0000          0000-00000000  0000          0000-00000000
  131.  
  132. Upper four    12 bits for    Lower four    Effect command.
  133. bits of sam-  note period.   bits of sam-
  134. ple number.                  ple number.
  135.  
  136.  
  137. */
  138.  
  139.  
  140. UWORD M15_npertab[60]={
  141.  
  142. /* -> Tuning 0 */
  143.  
  144.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  145.     856,808,762,720,678,640,604,570,538,508,480,453,
  146.     428,404,381,360,339,320,302,285,269,254,240,226,
  147.     214,202,190,180,170,160,151,143,135,127,120,113,
  148.     107,101,95,90,85,80,75,71,67,63,60,56
  149. };
  150.  
  151.  
  152. void M15_ConvertNote(MODNOTE *n)
  153. {
  154.     UBYTE instrument,effect,effdat,note;
  155.     UWORD period;
  156.  
  157.     /* extract the various information from the 4 bytes that
  158.        make up a single note */
  159.  
  160.     instrument=(n->a&0x10)|(n->c>>4);
  161.     period=(((UWORD)n->a&0xf)<<8)+n->b;
  162.     effect=n->c&0xf;
  163.     effdat=n->d;
  164.  
  165.     /* Convert the period to a note number */
  166.  
  167.     note=0;
  168.     if(period!=0){
  169.         for(note=0;note<60;note++){
  170.             if(period>=M15_npertab[note]) break;
  171.         }
  172.         note++;
  173.         if(note==61) note=0;
  174.     }
  175.  
  176.     if(instrument!=0){
  177.         UniInstrument(instrument-1);
  178.     }
  179.  
  180.     if(note!=0){
  181.         UniNote(note+23);
  182.     }
  183.  
  184.     UniPTEffect(effect,effdat);
  185. }
  186.  
  187.  
  188.  
  189. UBYTE *M15_ConvertTrack(MODNOTE *n)
  190. {
  191.     int t;
  192.  
  193.     UniReset();
  194.     for(t=0;t<64;t++){
  195.         M15_ConvertNote(n);
  196.         UniNewline();
  197.         n+=of.numchn;
  198.     }
  199.     return UniDup();
  200. }
  201.  
  202.  
  203.  
  204. BOOL M15_LoadPatterns(void)
  205. /*
  206.     Loads all patterns of a modfile and converts them into the
  207.     3 byte format.
  208. */
  209. {
  210.     int t,s,tracks=0;
  211.  
  212.     if(!AllocPatterns()) return 0;
  213.     if(!AllocTracks()) return 0;
  214.  
  215.     /* Allocate temporary buffer for loading
  216.        and converting the patterns */
  217.  
  218.     if(!(patbuf=(MODNOTE *)MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  219.  
  220.     for(t=0;t<of.numpat;t++){
  221.  
  222.         /* Load the pattern into the temp buffer
  223.            and convert it */
  224.  
  225.         for(s=0;s<(64U*of.numchn);s++){
  226.             patbuf[s].a=_mm_read_UBYTE(modfp);
  227.             patbuf[s].b=_mm_read_UBYTE(modfp);
  228.             patbuf[s].c=_mm_read_UBYTE(modfp);
  229.             patbuf[s].d=_mm_read_UBYTE(modfp);
  230.         }
  231.  
  232.         for(s=0;s<of.numchn;s++){
  233.             if(!(of.tracks[tracks++]=M15_ConvertTrack(patbuf+s))) return 0;
  234.         }
  235.     }
  236.  
  237.     return 1;
  238. }
  239.  
  240.  
  241.  
  242. BOOL M15_Load(void)
  243. {
  244.     int t;
  245.     INSTRUMENT *d;          /* new sampleinfo structure */
  246.     SAMPLE *q;
  247.     MSAMPINFO *s;           /* old module sampleinfo */
  248.  
  249.     /* try to read module header */
  250.  
  251.     if(!LoadModuleHeader(mh)){
  252.         myerr=ERROR_LOADING_HEADER;
  253.         return 0;
  254.     }
  255.  
  256.     /* set module variables */
  257.  
  258.     of.initspeed=6;
  259.     of.inittempo=125;
  260.     of.numchn=4;                                                    /* get number of channels */
  261.     of.modtype=strdup("15-instrument");             /* get ascii type of mod */
  262.     of.songname=DupStr(mh->songname,20);        /* make a cstr of songname */
  263.     of.numpos=mh->songlength;                       /* copy the songlength */
  264.     memcpy(of.positions,mh->positions,128);     /* copy the position array */
  265.  
  266.     /* Count the number of patterns */
  267.  
  268.     of.numpat=0;
  269.  
  270.     for(t=0;t<128;t++){             /* <-- BUGFIX... have to check ALL positions */
  271.         if(of.positions[t] > of.numpat){
  272.             of.numpat=of.positions[t];
  273.         }
  274.     }
  275.     of.numpat++;
  276.     of.numtrk=of.numpat*of.numchn;
  277.  
  278.     /* Finally, init the sampleinfo structures */
  279.  
  280.     of.numins=15;
  281.     if(!AllocInstruments()) return 0;
  282.  
  283.     s=mh->samples;          /* init source pointer */
  284.     d=of.instruments;       /* init dest pointer */
  285.  
  286.     for(t=0;t<of.numins;t++){
  287.  
  288.         d->numsmp=1;
  289.         if(!AllocSamples(d)) return 0;
  290.  
  291.         q=d->samples;
  292.  
  293.         /* convert the samplename */
  294.  
  295.         d->insname=DupStr(s->samplename,22);
  296.  
  297.         /* init the sampleinfo variables and
  298.            convert the size pointers to longword format */
  299.  
  300.         q->c2spd=finetune[s->finetune&0xf];
  301.         q->volume=s->volume;
  302.         q->loopstart=s->reppos;
  303.         q->loopend=q->loopstart+(s->replen<<1);
  304.         q->length=s->length<<1;
  305.         q->seekpos=0;
  306.  
  307.         q->flags=SF_SIGNED;
  308.         if(s->replen>1) q->flags|=SF_LOOP;
  309.  
  310.         /* fix replen if repend>length */
  311.  
  312.         if(q->loopend>q->length) q->loopend=q->length;
  313.  
  314.         s++;    /* point to next source sampleinfo */
  315.         d++;    /* point to next destiny sampleinfo */
  316.     }
  317.  
  318.     if(!M15_LoadPatterns()) return 0;
  319.     return 1;
  320. }
  321.  
  322.  
  323.  
  324. LOADER load_m15={
  325.     NULL,
  326.     "ProTracker MOD (15-instrument)",
  327.     "",
  328.     M15_Init,
  329.     M15_Test,
  330.     M15_Load,
  331.     M15_Cleanup
  332. };
  333.